/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.farent.solutions.plugins.stripes.hyperstripes.ext;

import com.farent.solutions.plugins.stripes.hyperstripes.core.HSActionBean;
import com.farent.solutions.plugins.stripes.hyperstripes.core.HyperstripesSession;
import javax.servlet.http.HttpServletRequest;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.SessionScope;
import net.sourceforge.stripes.controller.ActionResolver;
import net.sourceforge.stripes.controller.NameBasedActionResolver;
import net.sourceforge.stripes.exception.ActionBeanNotFoundException;
import net.sourceforge.stripes.exception.StripesServletException;

/**
 *
 * @author user
 */
public class HyperstripesActionResolver 
        extends NameBasedActionResolver implements ActionResolver
{

    private static final String HS_SESSION_KEY = "_hs_session_key";

    /**
     * Returns the ActionBean class that is bound to the UrlBinding supplied. If the action
     * bean already exists in the appropriate scope (request or session) then the existing
     * instance will be supplied.  If not, then a new instance will be manufactured and have
     * the supplied ActionBeanContext set on it.
     *
     * @param path a URL to which an ActionBean is bound, or a path starting with the URL
     *        to which an ActionBean has been bound.
     * @param context the current ActionBeanContext
     * @return a Class<ActionBean> for the ActionBean requested
     * @throws StripesServletException if the UrlBinding does not match an ActionBean binding
     */
    @Override
    public ActionBean getActionBean(ActionBeanContext context, String path) throws StripesServletException {
        Class<? extends ActionBean> beanClass = getActionBeanType(path);
        ActionBean bean;

        if (beanClass == null) {
            throw new ActionBeanNotFoundException(
                    path, getUrlBindingFactory().getPathMap());
        }

        String bindingPath = getUrlBinding(beanClass);
        boolean isHyperStripe = false;
        try {
            HttpServletRequest request = context.getRequest();
            Class<?>[] interfaces = beanClass.getInterfaces();
            for (int i = 0; i < interfaces.length; i++) {
                Class<?> class1 = interfaces[i];
                if( class1.getName().equals(HSActionBean.class.getName()))
                    isHyperStripe = true;
                break;
            }
            if ( isHyperStripe ) {
                HyperstripesSession hsSession =
                        (HyperstripesSession) request.getSession().getAttribute(HS_SESSION_KEY);
                if ( hsSession == null ) {
                    hsSession = new HyperstripesSession();
                    bean = makeNewActionBean(beanClass, context);
                    hsSession.getActionBeans().put(beanClass, bean);
                    request.getSession().setAttribute(HS_SESSION_KEY, hsSession);
                }
                else
                {
                    bean = (ActionBean) hsSession.getActionBeans().get(beanClass);

                    if (bean == null) {
                        bean = makeNewActionBean(beanClass, context);
                        request.getSession().setAttribute(bindingPath, bean);
                    }
                }
            }
            else if(beanClass.isAnnotationPresent(SessionScope.class)) {
                bean = (ActionBean) request.getSession().getAttribute(bindingPath);

                if (bean == null) {
                    bean = makeNewActionBean(beanClass, context);
                    request.getSession().setAttribute(bindingPath, bean);
                }
            }
            else {
                bean = (ActionBean) request.getAttribute(bindingPath);
                if (bean == null) {
                    bean = makeNewActionBean(beanClass, context);
                    request.setAttribute(bindingPath, bean);
                }
            }

            setActionBeanContext(bean, context);
        }
        catch (Exception e) {
            StripesServletException sse = new StripesServletException(
                "Could not create instance of ActionBean type [" + beanClass.getName() + "].", e);
            java.util.logging.Logger.getLogger(getClass().getName()).severe(sse.getMessage());
            throw sse;
        }

        assertGetContextWorks(bean);
        return bean;

    }
}
